`ifndef axi4_LITE_DRIVE_H
`define axi4_LITE_DRIVE_H

class axi4_lite_drive;
    virtual axi4_lite_bfm    bfm;
    //rand bit [31:00] data;

    //constraint c
    //{
        //data.size() == 5;
        //foreach(data[i])
            //data[i] inside {[0:65535]};
    //}

    function new(virtual axi4_lite_bfm b);
        bfm = b;
    endfunction
    /*-------------------------------------------------------------------------
    //description   :   初始化axi4-lite接口信号
    -------------------------------------------------------------------------*/
    extern task init();
    /*-------------------------------------------------------------------------
    //description   :   指定位置写入一个单位数据
    //addr指的是以字节为单位的地址, axi4 lite slave器件数据宽度至少为32bit
    //所以地址步增至少为4的倍数
    -------------------------------------------------------------------------*/
    extern task write(int addr, bit [31:00] data);
    /*-------------------------------------------------------------------------
    //description   :   指定位置写入len长度单位数据
    -------------------------------------------------------------------------*/
    extern task read(int addr);
endclass

task axi4_lite_drive::init();
    bfm.awaddr = 0;
    bfm.awvalid = 0;
    bfm.awprot = 0;

    bfm.wdata = 0;
    bfm.wstrb = 0;
    bfm.wvalid = 0;

    bfm.bready = 1;

    bfm.araddr = 0;
    bfm.arprot = 0;
    bfm.arvalid = 0;

    bfm.rready = 0;
    
endtask

/*-------------------------------------------------------------------------
//description   : 向指定地址写入一个dword（相当于burst一个单位）
//parameter     : addr, slave器件reg地址
//parameter     : data, 要写入的地址
//others        :
-------------------------------------------------------------------------*/
task axi4_lite_drive::write(int addr, bit [31:00] data);
    @ (posedge bfm.aclk);
    bfm.awprot = 0;
    bfm.awvalid = 1;
    bfm.awaddr = addr;

    bfm.wstrb = 4'b1111;
    bfm.wdata = data;
    bfm.wvalid = 1;

    wait (bfm.awready);
    @ (posedge bfm.aclk);
    bfm.awvalid = 0;
endtask

/*-------------------------------------------------------------------------
//description   : 从slave指定addr读取一个单位的数据
//parameter     : addr, slave器件reg地址
//others        :
-------------------------------------------------------------------------*/
task axi4_lite_drive::read(int addr);
    @ (posedge bfm.aclk);
    bfm.araddr = addr;
    bfm.arvalid = 1;
    wait (bfm.arready);
    @ (posedge bfm.aclk);
    bfm.arvalid = 0;

    bfm.rready = 1;
    wait (bfm.rvalid);
    @ (posedge bfm.aclk);
    bfm.rready = 0;
endtask
`endif
